package dao

import (
	"context"
	"strings"
	"time"

	"github.com/ego-component/egorm"
)

const (
	duplicateErr = "Duplicate"
)

type MessageDAO interface {
	Insert(ctx context.Context, msg Message) (int64, error)
	GetHistoryMessages(ctx context.Context, cid int64, lastMsgID int64, offset, limit int) ([]Message, error)
}

type Message struct {
	ID          int64  `gorm:"column:id; primaryKey; autoIncrement"`
	Key         string `gorm:"column:key; type:varchar(255);uniqueIndex:idx_msg_key,length:255"`
	ContentType int32  `gorm:"column:content_type"`
	Content     []byte `gorm:"column:content;type:BLOB"`
	SendID      int64  `gorm:"column:send_id;index"`
	SendTime    int64  `gorm:"column:send_time;index"`
	Ctime       int64  `gorm:"column:ctime"`
	Cid         int64  `gorm:"column:cid"`
}

func (m Message) TableName() string {
	return "messages"
}

type gormMessageDAO struct {
	db *egorm.Component
}

func NewGORMMessageDAO(db *egorm.Component) MessageDAO {
	return &gormMessageDAO{
		db: db,
	}
}

func (g *gormMessageDAO) Insert(ctx context.Context, msg Message) (int64, error) {
	msg.Ctime = time.Now().UnixMilli()
	err := g.db.WithContext(ctx).
		Create(&msg).Error
	if err != nil {
		if strings.Contains(err.Error(), duplicateErr) {
			var ans Message
			err = g.db.WithContext(ctx).
				Model(&Message{}).
				Where("msg_key = ?", msg.Key).First(&ans).Error
			return ans.ID, err
		}
		return 0, err
	}
	return msg.ID, nil
}

func (g *gormMessageDAO) GetHistoryMessages(ctx context.Context, cid, lastMsgID int64, offset, limit int) ([]Message, error) {
	var messages []Message
	query := g.db.WithContext(ctx).
		Where("cid = ? AND id > ? ", cid, lastMsgID)
	err := query.Order("id asc").
		Offset(offset).
		Limit(limit).
		Find(&messages).Error
	return messages, err
}
